#!/bin/bash
# *************************************
# 功能: 主功能函数所依赖的功能函数
# 作者: 王树森
# 联系: wangshusen@sswang.com
# 版本: v0.1
# 日期: 2023-04-13
# *************************************

expect_cmd='/usr/bin/expect'

# expect环境部署
expect_install(){
  # 判断expect是否安装
  if [ -f "${expect_cmd}" ]; then
    echo -e "\033[31mexpect环境已经部署完毕了!!!\033[0m"
  else
    # 安装expect
    read -p "请输入您准备以哪种方式安装expect(online|offline): " install_type
    install_type=${install_type:-online}
    if [ "${install_type}" == "online" ]; then
      # 指定安装
      "${cmd_type}" install expect -y && echo -e "\e[32mexpect软件安装成功!!!\e[0m" || (echo -e "\e[32mexpect软件安装失败!!!\e[0m" && exit)
    else
      echo "离线安装"
    fi
  fi  
}

# ssh秘钥生成
sshkey_create(){
  current_user=$(whoami)
  [ "${current_user}" == "root" ] && user_dir='/root' || user_dir="/home/${current_user}"
  [ -d "${user_dir}/.ssh" ] && rm -rf "${user_dir}/.ssh"
  # 生成ssh秘钥对儿
  ssh-keygen -t rsa  -P "" -f "${user_dir}/.ssh/id_rsa"
  echo -e "\e[32mssh秘钥对儿创建完毕!!!\e[0m"
}

# hosts文件生成
hosts_create(){
  # 优化1：考虑创建hosts文件时的旧有记录处理
  for i in $(awk '/kuber/{print $1}' "${conf_dir}/${host_name}");do
    sed -i "/$i/d" "${host_file}"
  done
  # 增加当前集群的节点主机名解析记录
  awk '$0~"kubernetes-"{print $1,$2".sswang.com",$2}' "${conf_dir}/${host_name}" >> "${host_file}"
  echo -e "\e[32mhosts文件创建完毕!!!\e[0m"
}

# ssh 跨主机免密码认证
sshkey_auth_func(){
  # 接收参数
  local ip_list="$*"
  # 执行跨主机免密码操作
  local cmd="ssh-copy-id -i $HOME/.ssh/id_rsa.pub "
  for ip in ${ip_list}; do
    # local ip_target="${login_user}@${ip}"
    # 调试1 ：因为 config/hosts 和 /etc/hosts 内容不一样，我们用的是/etc/hosts格式
    # local host=$(grep $ip ${host_file} | awk '{print $2}')
    # local host_target="${login_user}@${host}"
    # expect_autoauth_func ${cmd} ${ip_target}
    # expect_autoauth_func ${cmd} ${host_target}
    # 调试2：主机名解析记录，在多种场景下，长短主机名都可能用到，所以这三个都做认证
    for addr in $(grep $ip ${host_file}); do
      # 借助循环构造多格式主机目标
      local target="${login_user}@${addr}"
      expect_autoauth_func "${cmd}" "${target}"
      echo -e "\e[32m主机 $addr 已经实现跨主机免密码认证!!!\e[0m"
    done
  done
}

# expect 实现自动化命令执行
expect_autoauth_func(){
  # 接收参数
  local remote_cmd="$*"
  # expect的全程干预
  /usr/bin/expect -c "
    spawn ${remote_cmd}
    expect {
      \"yes/no\" {send \"yes\r\"; exp_continue}
      \"*password*\" {send \"${login_pass}\r\"; exp_continue}
      \"*password*\" {send \"${login_pass}\r\"}
    }"
}

# 远程传输文件
# scp_file(){
  # 接收参数
#   local ip_list="$*"
  # 远程传输文件
# for ip in ${ip_list}; do
#   scp "${host_file}" "${login_user}@${ip}:${host_file}"
#  done
#}

scp_file(){
  # 接收参数
  local target_dir=$(echo $* | awk '{print $NF}')
  local source_file=$(echo $* | awk '{print $(NF-1)}')
  local ip_list=$(echo $* | awk '{$NF=null;$(NF-1)=null;print $0}')
  local filename=$(basename ${source_file})
  local target_file="${target_dir}/${filename}"
  # 远程传输文件
  for ip in ${ip_list}; do
    scp "${source_file}" "${login_user}@${ip}:${target_file}"
  done
}

# 跨主机设定主机名
set_hostname(){
  # 接收参数
  local ip_list="$*"
  # 远程执行命令
  for ip in ${ip_list}; do
    local remote_host="${login_user}@${ip}"
    local hostname=$(grep ${ip} ${host_file} | awk '{print $NF}')
    ssh ${remote_host} "hostnamectl set-hostname ${hostname}"
  done
}

# 生成ip列表
create_ip_list(){
  # 接收参数
  local ip_net="$1"
  local ip_tail="$2"
  local ip_list=""
  # 生成ip列表
  for i in $(eval echo ${ip_tail}); do
    ip_addr=$(echo -n "${ip_net}.${i} ")
    ip_list="${ip_list}${ip_addr}"
  done
  echo "${ip_list}"
}

# 软件源同步
repo_update(){
  # 接收参数
  local ip_list="$*"
  # 定制更新的命令
  
  # if [ "${os_type}" == "centos" ]; then
  #   update_cmd="${cmd_type} makecache fast"
  # else
  #   update_cmd="${cmd_type} update -y"
  # fi
  # 优化：所有主机的关键源优化，自动确定
  # 注意：这里依赖于所有远程主机，有自己的软件源文件 repo | sources.list
  # 远程执行更新命令
  for ip in ${ip_list}; do
    remote_os_status=$(ssh "${login_user}@${ip}" "grep -i ubuntu /etc/issue")
    [ -n "${remote_os_status}" ] && local os_type="Ubuntu" || local os_type="CentOS"
    if [ "${os_type}" == "CentOS" ]; then
      ssh "${login_user}@${ip}" "yum makecache fast"
    else
      ssh "${login_user}@${ip}" "rm -rf /var/lib/dpkg/lock*; apt update"
    fi
    echo -e "\033[32m主机 ${ip} 软件源更新完毕!!!\033[0m"
  done
}

# 输出符号
echo_tag(){
  # 常见方法：
  # echo {1..30} | sed 's/[0-9]/=/g' | sed 's/ //g' 
  # seq -s "=" 100 | sed 's/[0-9]//g'
  # echo | awk '{for(i=1;i<=100;i++){printf "="}}{printf "\n"}'

  # 接收参数
  tag="$1"
  num="$2"
  
  # 输出指定长度的内容
  seq -s "${tag}" ${num} | sed 's/[0-9]//g'
}

# 定制旋转函数
waiting(){
  # 接收参数
  local end_time="$1"
  # 定制初始参数
  time=0
  while [ $time -lt "$end_time" ]; do
  # 开始循环
    for tag in "\\" "|" "/" "-"; do
      # 循环遍历符号
      printf "%c\r" "$tag"
      sleep 0.2
    done
    # 结束(-10s)
    let time+=1
  done
}

# 定制一键通用基础环境功能函数
one_key_base_env(){
  # 功能逻辑
  echo -e "\e[33m开始执行基本环境部署...\e[0m"
  expect_install
  sshkey_create
  hosts_create
  echo -e "\e[33m开始执行跨主机免密码认证...\e[0m"
  sshkey_auth_func "${all_node_list}"
  echo -e "\e[33m开始执行同步集群hosts...\e[0m"
  scp_file ${all_node_list} "${host_file}" "${host_target_dir}"
  echo -e "\e[33m开始执行设定集群主机名...\e[0m"
  set_hostname ${all_node_list}
  echo -e "\e[33m开始执行更新软件源...\e[0m"
  repo_update "${all_node_list}"
}
